package com.wetao.module_demo_cyh;

import android.Manifest;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.alibaba.android.arouter.facade.annotation.Route;
import com.tstudy.blepenlib.BlePenStreamManager;
import com.tstudy.blepenlib.callback.BleGattCallback;
import com.tstudy.blepenlib.callback.BlePenStreamCallback;
import com.tstudy.blepenlib.callback.BleScanCallback;
import com.tstudy.blepenlib.data.BleDevice;
import com.tstudy.blepenlib.data.CoordinateInfo;
import com.tstudy.blepenlib.exception.BleException;
import com.wetao.lib_common.ConstantArouter;
import com.wetao.lib_common.base.BaseActivity;
import com.wetao.lib_common.contract.EmptyCon;
import com.wetao.lib_common.presenter.EmptyPre;
import com.wetao.lib_common.tsdBlePen.MyLicense;
import com.wetao.lib_common.tsdBlePen.TsdService;
import com.wetao.lib_common.utils.LogUtils;
import com.wetao.module_demo_cyh.blepen.DeviceAdapter;

import org.greenrobot.eventbus.EventBus;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import static com.tstudy.blepenlib.constant.Constant.WARN_APP_MODE;
import static com.tstudy.blepenlib.constant.Constant.WARN_BATTERY;
import static com.tstudy.blepenlib.constant.Constant.WARN_BOOT_MODE;
import static com.tstudy.blepenlib.constant.Constant.WARN_MEMORY;
import static com.tstudy.blepenlib.constant.Constant.WARN_NOT_VERIFY_MODE;
import static com.tstudy.blepenlib.constant.Constant.WARN_VERIFY_MODE;

@Route(path = ConstantArouter.PATH_DEMOCYH_YUNDIEPENTESTACTIVITY)
public class YundiePenTestActivity extends BaseActivity<EmptyCon.View, EmptyPre>
        implements EmptyCon.View, View.OnClickListener{

    private static final String TAG = "YundiePenTestActivity_tag";
    private static final int REQUEST_CODE_OPEN_GPS = 1;
    private static final int REQUEST_CODE_PERMISSION_LOCATION = 2;
    private static final int REQUEST_OPEN_BT_CODE = 3;

    private BleDevice mBleDevice;
    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS", Locale.CHINA);
    private BlePenStreamCallback mBlePenStreamCallback;
    private TextView txt_battery;
    private TextView txt_memory;
    private Context mContext;
    private BleGattCallback mBleGattCallback;
    private ProgressDialog progressDialog;

    private Button btn_scan;
    private ImageView img_loading;

    private Animation operatingAnim;
    private DeviceAdapter mDeviceAdapter;
    private LinearLayout layout_scan;
    private FrameLayout layout_debugging;
    private RelativeLayout ly_location_warn;

    @Override
    public int getLayoutId() {
        return R.layout.yundie_pen_test_activity;
    }

    @Override
    public EmptyPre createPresenter() {
        return new EmptyPre(this);
    }

    @Override
    public EmptyCon.View createView() {
        return this;
    }

    @Override
    public boolean getIsBindTsdService() {
        return false;
    }

    @Override
    public TsdService.OnDataReceiveListener getTsdServiceDataReceiveListener() {
        return null;
    }

    @Override
    public void init() {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        initView();
        mContext = YundiePenTestActivity.this;
        boolean initSuccess = BlePenStreamManager.getInstance().init(mContext, MyLicense.getBytes());
        if (initSuccess) {
            BlePenStreamManager.getInstance().enableLog(true);
            initListener();
        } else {
            Toast.makeText(this, "初始化失败，请到开放平台申请授权或检查设备是否支持蓝牙BLE", Toast.LENGTH_LONG).show();
        }
    }


    @Override
    protected void onResume() {
        super.onResume();
        if (mDeviceAdapter != null) {
            mDeviceAdapter.clear();
            mDeviceAdapter.notifyDataSetChanged();
        }
        if (!gpsIsOpen(mContext)) {
            ly_location_warn.setVisibility(View.VISIBLE);
        }else {
            ly_location_warn.setVisibility(View.GONE);
        }

    }

    /**
     * 判断GPS是否开启，GPS或者AGPS开启一个就认为是开启的
     *
     * @param context
     * @return true 表示开启
     */
    public boolean gpsIsOpen(final Context context) {
        LocationManager locationManager
                = (LocationManager) context.getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        // 通过GPS卫星定位，定位级别可以精确到街（通过24颗卫星定位，在室外和空旷的地方定位准确、速度快）
        boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        boolean passive = locationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER);
        // 通过WLAN或移动网络(3G/2G)确定的位置（也称作AGPS，辅助GPS定位。主要用于在室内或遮盖物（建筑群或茂密的深林等）密集的地方定位）
        boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        LogUtils.i( "gpsIsOpen: gps" + gps + "    passive" + passive + "     network " + network);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            //版本大于6.0，必须打开gps才可以搜索到蓝牙
            if (gps) {
                return true;
            }
        } else{
            //在版本低于此的时候，做一些处理
            if (gps || network || passive) {
                return true;
            }
        }
        return false;
    }

    private void initListener() {
        //通讯数据流回调
        mBlePenStreamCallback = new BlePenStreamCallback() {

            @Override
            public void onRemainBatteryAndMemory(final int batteryPercent, final int memoryPercent, final int memoryByteNum) {
                LogUtils.i( "batteryPercent: " + batteryPercent + "%");
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        txt_battery.setText(batteryPercent + "%");
                        txt_memory.setText(memoryPercent + "%，已使用字节数：" + memoryByteNum);

                    }
                });
            }

            @Override
            public void onCoordDraw(CoordinateInfo coordinateInfo) {
                /**
                 * 输出离线数据坐标信息
                 * @param state down/move/up
                 * @param pageAddress 点阵地址
                 * @param nX 坐标X
                 * @param nY 坐标Y
                 * @param nForce 压力值
                 * @param strokeNum 笔画数
                 * @param time 时间戳
                 * @param offLineDataAllSize 总离线字节数
                 * @param offLineDateCurrentSize 已上传字节数
                 */

                EventBus.getDefault().post(coordinateInfo);
            }

            @Override
            public void onWarnActiveReport(int statusNum) {
                //0x05  电池电量低警告  0x08 存储空间警告
                switch (statusNum) {
                    case WARN_BATTERY:
                        LogUtils.i( "handleActiveReport: 电池电量低警告");
                        break;
                    case WARN_MEMORY:
                        LogUtils.i( "handleActiveReport: 存储空间警告");
                        break;
                    case WARN_BOOT_MODE:
                        LogUtils.i(  "handleActiveReport: WARN_BOOT_MODE");
                        break;
                    case WARN_APP_MODE:
                        LogUtils.i( "handleActiveReport: WARN_APP_MODE");
                        break;
                    case WARN_VERIFY_MODE:
                        LogUtils.i(  "handleActiveReport: WARN_VERIFY_MODE");
                        //verifyPassword();
                        Toast.makeText(mContext, "需要验证密码才能使用实时模式", Toast.LENGTH_LONG).show();
                        break;
                    case WARN_NOT_VERIFY_MODE:
                        LogUtils.i(  "handleActiveReport: WARN_NOT_VERIFY_MODE");
                        break;
                    default:
                }
            }

            @Override
            public void onNewSession(final String hardVersion, final String softVersion, final String syncNum) {
                //Version serial number
                final String msg = "hardVersion：" + hardVersion + "  softVersion:" + softVersion + "   syncNum:" + syncNum;
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
//                        txt_errorCount.setText(hardVersion);
                        if (!TextUtils.isEmpty(softVersion)) {
                            Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }

            @Override
            public void onPenTimeOrPenOffTime(int statusNum, long penTime) {
                if (statusNum == 1) {
                    //如果与当前系统时间差一分钟以上，自动同步时间
                    long timeMillis = System.currentTimeMillis();
                    if (Math.abs(penTime - timeMillis) > 1000 * 60) {
                        BlePenStreamManager.getInstance().setPenRTC(timeMillis);
                    }
                    String formatTime = simpleDateFormat.format(new Date(penTime));
                    Toast.makeText(mContext, formatTime, Toast.LENGTH_SHORT).show();
                } else if (statusNum == 2) {
                    LogUtils.i( "onPenTimeOrPenOffTime: " + penTime);
                    Toast.makeText(mContext, "关机时间：" + penTime + " minute", Toast.LENGTH_SHORT).show();
                }
            }
        };

        //连接回调
        mBleGattCallback = new BleGattCallback() {
            @Override
            public void onStartConnect() {
                progressDialog.setMessage("正在连接蓝牙点阵笔:" + mBleDevice.getName());
                progressDialog.show();
            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                img_loading.clearAnimation();
                img_loading.setVisibility(View.INVISIBLE);
                btn_scan.setText(getString(R.string.start_scan));
                progressDialog.dismiss();
                Toast.makeText(YundiePenTestActivity.this, getString(R.string.connect_fail), Toast.LENGTH_LONG).show();
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice) {
                mBleDevice = bleDevice;
                progressDialog.dismiss();
                mDeviceAdapter.addDevice(0, bleDevice);
                mDeviceAdapter.notifyDataSetChanged();
                if (layout_scan.getVisibility() == View.VISIBLE) {
                    layout_scan.setVisibility(View.GONE);
                    layout_debugging.setVisibility(View.VISIBLE);
                }
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice) {
                progressDialog.dismiss();
                mDeviceAdapter.removeDevice(bleDevice);
                mDeviceAdapter.notifyDataSetChanged();
                LogUtils.i( "isActiveDisConnected:" + isActiveDisConnected + "    onDisConnected: " + bleDevice.getName());
                if (isActiveDisConnected) {
                    Toast.makeText(YundiePenTestActivity.this, getString(R.string.active_disconnected), Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(YundiePenTestActivity.this, getString(R.string.disconnected), Toast.LENGTH_LONG).show();
                }
                if (layout_debugging.getVisibility() == View.VISIBLE) {
                    layout_debugging.setVisibility(View.GONE);
                    layout_scan.setVisibility(View.VISIBLE);
                }
                mDeviceAdapter.clear();
                mDeviceAdapter.notifyDataSetChanged();
            }
        };

    }

    @Override
    protected void onDestroy() {
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        BlePenStreamManager.getInstance().disconnect(mBleDevice);
        LogUtils.i(  "onDestroy: MainActivity");
        super.onDestroy();
    }

    @Override
    public void onClick(View v) {
        if(v.getId() == R.id.btn_scan) {
            if (btn_scan.getText().equals(getString(R.string.start_scan))) {
                checkPermissions();
            } else if (btn_scan.getText().equals(getString(R.string.stop_scan))) {
                BlePenStreamManager.getInstance().cancelScan();
            }
        }
    }

    private void initView() {
        ly_location_warn = findViewById(R.id.ly_location_warn);
        ly_location_warn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivityForResult(intent, REQUEST_CODE_OPEN_GPS);
            }
        });

        layout_scan = findViewById(R.id.layout_scan);
        layout_debugging = findViewById(R.id.layout_debugging);

        btn_scan = (Button) findViewById(R.id.btn_scan);
        btn_scan.setText(getString(R.string.start_scan));
        btn_scan.setOnClickListener(this);

        img_loading = (ImageView) findViewById(R.id.img_loading);
        operatingAnim = AnimationUtils.loadAnimation(this, R.anim.rotate);
        operatingAnim.setInterpolator(new LinearInterpolator());
        progressDialog = new ProgressDialog(this);

        mDeviceAdapter = new DeviceAdapter(this);
        mDeviceAdapter.setOnDeviceClickListener(new DeviceAdapter.OnDeviceClickListener() {
            @Override
            public void onConnect(BleDevice bleDevice) {
                if (!BlePenStreamManager.getInstance().isConnected(bleDevice)) {
                    //如果当前设备未连接，取消扫描，连接选中设备。
                    BlePenStreamManager.getInstance().cancelScan();
                    connect(bleDevice);
                }
            }

            @Override
            public void onDisConnect(final BleDevice bleDevice) {
                if (BlePenStreamManager.getInstance().isConnected(bleDevice)) {
                    //如果当前设备已连接，断开连接。
                    BlePenStreamManager.getInstance().disconnect(bleDevice);
                }
            }

            @Override
            public void onDetail(BleDevice bleDevice) {

            }
        });
        ListView listView_device = (ListView) findViewById(R.id.list_device);
        listView_device.setAdapter(mDeviceAdapter);
        txt_battery = findViewById(R.id.txt_battery);
        txt_memory = findViewById(R.id.txt_memory);

        Button enter_draw = findViewById(R.id.enter_draw);
        enter_draw.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //跳到绘制界面
                Intent intent = new Intent(YundiePenTestActivity.this, YundiePenTestDrawActivity.class);
                intent.putExtra("penMac", mBleDevice.getMac());
                startActivity(intent);

            }
        });

        //获取笔端信息
        Button btn_pen_info = findViewById(R.id.btn_pen_info);
        btn_pen_info.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                BlePenStreamManager.getInstance().getPenInfo();
            }
        });

        //清空缓存
        Button btn_delete_memory_cache = findViewById(R.id.btn_delete_memory_cache);
        btn_delete_memory_cache.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                BlePenStreamManager.getInstance().clearMemoryCache();
            }
        });

        //断开连接
        Button btn_disconnect = findViewById(R.id.btn_disconnect);
        btn_disconnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (BlePenStreamManager.getInstance().isConnected(mBleDevice)) {
                    //如果当前设备已连接，断开连接。
                    BlePenStreamManager.getInstance().disconnect(mBleDevice);
                }
            }
        });
    }

    private void startScan() {
        //扫描回调
        BleScanCallback callback = new BleScanCallback() {
            @Override
            public void onScanStarted(boolean success) {
                mDeviceAdapter.clearScanDevice();
                mDeviceAdapter.notifyDataSetChanged();
                img_loading.startAnimation(operatingAnim);
                img_loading.setVisibility(View.VISIBLE);
                btn_scan.setText(getString(R.string.stop_scan));
            }

            @Override
            public void onLeScan(BleDevice bleDevice) {
                super.onLeScan(bleDevice);
            }

            @Override
            public void onScanning(BleDevice bleDevice) {
                mDeviceAdapter.addDevice(bleDevice);
                mDeviceAdapter.notifyDataSetChanged();
            }

            @Override
            public void onScanFinished(List<BleDevice> scanResultList) {
                img_loading.clearAnimation();
                img_loading.setVisibility(View.INVISIBLE);
                btn_scan.setText(getString(R.string.start_scan));
            }
        };
        BlePenStreamManager.getInstance().scan(callback);
    }

    private void connect(final BleDevice bleDevice) {
        //连接回调
        mBleDevice = bleDevice;
        BlePenStreamManager.getInstance().connect(bleDevice, mBleGattCallback, mBlePenStreamCallback);
    }

    @Override
    public final void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                                 @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE_PERMISSION_LOCATION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //用户允许改权限，0表示允许，-1表示拒绝 PERMISSION_GRANTED = 0， PERMISSION_DENIED = -1
                startScan();
            } else {
                //这里进行权限被拒绝的处理
                if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
                    Toast.makeText(YundiePenTestActivity.this, "自Android 6.0开始需要打开位置权限才可以搜索到Ble设备", Toast.LENGTH_LONG).show();
                }
            }
        }
    }

    private void checkPermissions() {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {
            Toast.makeText(this, "检查设备是否支持蓝牙BLE", Toast.LENGTH_LONG).show();
            return;
        }
        if (!bluetoothAdapter.isEnabled()) {
            Toast.makeText(this, getString(R.string.please_open_blue), Toast.LENGTH_LONG).show();
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, REQUEST_OPEN_BT_CODE);
            return;
        }
        //如果 API level 是大于等于 23(Android 6.0) 时
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            //判断是否具有权限
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                //判断是否需要向用户解释为什么需要申请该权限
                if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
                    Toast.makeText(YundiePenTestActivity.this, "自Android 6.0开始需要打开位置权限才可以搜索到Ble设备", Toast.LENGTH_LONG).show();
                }
                //请求权限
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                        REQUEST_CODE_PERMISSION_LOCATION);
            } else {
                startScan();
            }
        } else {
            startScan();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_OPEN_BT_CODE) {
            if (resultCode == RESULT_OK) {
                checkPermissions();
            } else {
                Toast.makeText(mContext, "拒绝蓝牙权限", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        LogUtils.i("m1:--onKeyDown keyCode = " + keyCode);
        switch (keyCode) {
            case KeyEvent.KEYCODE_1:{
                if (ly_location_warn.getVisibility() == View.VISIBLE) {
                    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    startActivityForResult(intent, REQUEST_CODE_OPEN_GPS);
                }
            }break;
            case KeyEvent.KEYCODE_2:{
                if (layout_scan.getVisibility() == View.VISIBLE) {
                    if (btn_scan.getText().equals(getString(R.string.start_scan))) {
                        checkPermissions();
                    }
                }
            }break;
            case KeyEvent.KEYCODE_3:{
                if (layout_scan.getVisibility() == View.VISIBLE) {
                    if (btn_scan.getText().equals(getString(R.string.stop_scan))) {
                        BlePenStreamManager.getInstance().cancelScan();
                    }
                }
            }break;
            case KeyEvent.KEYCODE_4:{
                if (layout_scan.getVisibility() == View.GONE) {
                    Intent intent = new Intent(YundiePenTestActivity.this, YundiePenTestDrawActivity.class);
                    String macStr = mBleDevice.getMac();
                    intent.putExtra("penMac", macStr);
                    startActivity(intent);
                }
            }break;
            case KeyEvent.KEYCODE_5:{
                if (layout_scan.getVisibility() == View.GONE) {
                    BlePenStreamManager.getInstance().getPenInfo();
                }
            }break;
            case KeyEvent.KEYCODE_6:{
                if (layout_scan.getVisibility() == View.GONE) {
                    BlePenStreamManager.getInstance().clearMemoryCache();
                    BlePenStreamManager.getInstance().getPenInfo();
                }
            }break;
            case KeyEvent.KEYCODE_7:{
                if (layout_scan.getVisibility() == View.VISIBLE) {
                    if(mDeviceAdapter != null) {
                        mDeviceAdapter.enterPosition();
                    }
                }
            }break;
            case KeyEvent.KEYCODE_8:{
                if (layout_scan.getVisibility() == View.GONE) {
                    if (BlePenStreamManager.getInstance().isConnected(mBleDevice)) {
                        //如果当前设备已连接，断开连接。
                        BlePenStreamManager.getInstance().disconnect(mBleDevice);
                    }
                }
            }break;


            case KeyEvent.KEYCODE_DPAD_CENTER:{

                return true;
            }

            case KeyEvent.KEYCODE_DPAD_UP:{
                if (layout_scan.getVisibility() == View.VISIBLE) {
                    if(mDeviceAdapter != null) {
                        mDeviceAdapter.upPosition();
                    }
                }
                return true;
            }
            case KeyEvent.KEYCODE_DPAD_DOWN:{
                if (layout_scan.getVisibility() == View.VISIBLE) {
                    if(mDeviceAdapter != null) {
                        mDeviceAdapter.downPosition();
                    }
                }
                return true;
            }

        }
        return super.onKeyDown(keyCode, event);
    }
}
